package cn.anxin.a9.avplayer;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;

public class AVGLMonitor
        extends GLSurfaceView {
    private final static String TAG = "rnd2dplayer";

    private AVGLRender renderer = null;
    private int mCurVideoWidth = 0;
    private int mCurVideoHeight = 0;
    private byte[] videoBuffer;
    private int NONE = 0,DRAG = 1,ZOOM = 2;
    private int state = NONE;
    private ScaleGestureDetector scaleGestureDetector;
    private float mLastX,mLastY;
    private float preScale = 1f;
    private boolean scalable = false;
    private float minScale = 1f,maxScale = 4f;

    public AVGLMonitor(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.renderer = new AVGLRender(this);
        setRenderer(this.renderer);
        scaleGestureDetector = new ScaleGestureDetector(context,new ScaleListener());
    }

    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            AVGLMonitor.this.renderer.writeSample(AVGLMonitor.this.videoBuffer, AVGLMonitor.this.mCurVideoWidth, AVGLMonitor.this.mCurVideoHeight);
        }
    };

    protected void setYuvFrameData(byte[] yuvdata, int w, int h) {
        if ((this.mCurVideoWidth != w) || (this.mCurVideoHeight != h)) {
            this.mCurVideoWidth = w;
            this.mCurVideoHeight = h;
            this.videoBuffer = null;
            this.videoBuffer = new byte[this.mCurVideoWidth * this.mCurVideoHeight * 3 / 2 + 256];
        }
        if (yuvdata.length > this.videoBuffer.length) {
            return;
        }
        System.arraycopy(yuvdata, 0, this.videoBuffer, 0, yuvdata.length);

        Message msg = new Message();
        this.handler.sendMessage(msg);
    }

    private void refreshView(){
        this.requestRender();
    }

    public void setMaxScaleLevel(float level) {
        this.maxScale = level;
    }

    public void setScalable(boolean scalable){
        this.scalable = scalable;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(!scalable){
            return false;//其他监听器继续处理
        }
        float x, y;
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            state = DRAG;
        } else if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
            state = ZOOM;
        }
        if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP) {
            state = NONE;
        }
        if (state == ZOOM) {

            scaleGestureDetector.onTouchEvent(event);
            return true;
        }
        if (1.0f < preScale || state == DRAG) {
            x = event.getRawX();
            y = event.getRawY();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mLastX = event.getRawX();
                    mLastY = event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    float dx = x - mLastX;
                    float dy = -(y - mLastY);
                    renderer.setTrans(dx, dy);
                    refreshView();
                    mLastX = x;
                    mLastY = y;
                    break;

                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    break;
            }
            return true;
        }else{
            return false;
        }
    }

    private AVGLListener listener;
    public void setAVGLListener(AVGLListener listener){
        this.listener = listener;
    }

    public class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener{
        private float focusX;
        private float focusY;

        @Override
        public boolean onScale(ScaleGestureDetector d) {
            float currentSpan = d.getCurrentSpan();
            float previousSpan = d.getPreviousSpan();
            float scaleX = d.getCurrentSpanX() - d.getPreviousSpanX();
            float scaleY = d.getCurrentSpanY() - d.getPreviousSpanY();
            float currentScale = d.getScaleFactor() * preScale;
//                float currentScale = currentSpan / previousSpan; // same as getScaleFactor
            Log.d("scale", String.format("scale: %f, CurrentSpan: %f, PreviousSpan: %f, computed scale: %f",
                    d.getScaleFactor(),
                    d.getCurrentSpan(),
                    d.getPreviousSpan(),
                    d.getCurrentSpan()/d.getPreviousSpan()
            ));
//                float scale = preScale * currentScale;
            if(currentScale < minScale){
                currentScale = minScale;
            }else if (currentScale > maxScale){
                currentScale = maxScale;
            }
//            renderer.setScale(d.getFocusX(), d.getFocusY(), scaleX, scaleY, currentScale);
            renderer.setScale(focusX, focusY, scaleX, scaleY, currentScale);
            listener.onScale(currentScale);
            refreshView();
            preScale = currentScale;
//            }
            return false;
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector d) {
            focusX = d.getFocusX();
            focusY = d.getFocusY();
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            //发送 scale 结束事件
        }

    }
}
